home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / keyb / fixpat12.zip / FIXPATH.C-- < prev    next >
Text File  |  1994-04-08  |  6KB  |  179 lines

  1. /*
  2.     NAME:  FIXPATH.C--
  3.     DESCRIPTION:  TSR that removes the trailing backslash in command line
  4.     AUTHOR:  Jean-Marc Lasgouttes (Jean-Marc.Lasgouttes@inria.fr)
  5.     VERSION: 1.2
  6. */
  7.  
  8. // First, some compilation directives 
  9.  
  10. ? alignword FALSE
  11. ? parsecommandline TRUE
  12.  
  13. // Then, some useful definitions
  14.  
  15. ? include "DOS.H--"
  16. ? include "STRING.H--"
  17.  
  18. ? define OLD21_OFS 0x0000    // Offset where holding the address of the old handler
  19. ? define NEW21_OFS 0x0004    // Offset at which the interrupt routine resides
  20.  
  21. byte progname = "FIXPATH";
  22. ? define len_progname 8
  23. byte usage = "Usage :   FIXPATH [/U]\n\n"
  24.              "   /U uninstalls FixPath\n$";
  25.  
  26. // Now, the serious things can begin
  27.  
  28. // Resident routine ///////////////////////////////////////////////////////
  29.  
  30. : void FIXPATH()  // removes trailing backslash in the command line
  31. {                 //   DS:BX points to the command line
  32.   $ MOV  BX, DX
  33.   $ CMP  DSBYTE[BX+2], 0x20; // test whether the first character is a space
  34.   $ JZ   END;
  35.   $ INC  BX;
  36. LOOP:
  37.   $ INC  BX;
  38.   $ CMP  DSBYTE[BX], 0x0D;   // test for end of input
  39.   $ JZ   END;
  40.   $ CMP  DSBYTE[BX], 0x20;   // test for space
  41.   $ JZ   LOOP2;
  42.   $ CMP  DSBYTE[BX], 0x3A;   // test for colon
  43.   $ JZ   LOOP2;
  44.   $ CMP  DSWORD[BX], 0x205C; // test for backslash plus space 
  45.   $ JZ   REPLACE;
  46.   $ CMP  DSWORD[BX], 0x0D5C; // test for backslash plus carriage return
  47.   $ JNZ  LOOP;
  48. REPLACE:
  49.   $ MOV  DSBYTE[BX], 0x20;   // replace backslash with space
  50.   $ JMP  LOOP;
  51. LOOP2:
  52.   $ INC  BX;
  53.   $ CMP  DSBYTE[BX], 0x0D;   // test for end of input
  54.   $ JNZ  LOOP;
  55. END:
  56. }
  57.  
  58. word olddoshandle[2] = {0,0};    // Address of the old interrupt handler
  59.  
  60. interrupt doshandler()    // this is called every time INT 0x21 is invoked
  61. {
  62.   $ PUSHF;
  63.   $ CMP AH, 0x0A; 
  64.   $ JZ  DOFIX;
  65.   $ POPF;
  66.   $ JMP CSDWORD[OLD21_OFS];
  67. DOFIX:
  68.   $ CALL CSDWORD[OLD21_OFS]; // call the old handler to do the edit work
  69.   $ PUSH BX;            // save BX; it will be restored later
  70.   @FIXPATH();          // Do the real work
  71. END:
  72.   $ POP  BX;            // Restore BX
  73. }
  74.  
  75. word endofdoshandle=0;  // used to compute the length of the interrupt routine
  76.  
  77.  
  78. // Transient part of the program //////////////////////////////////////////
  79.  
  80. // The following functions could be included in a general library
  81.  
  82. word instcheck(word name, len) // installation check
  83. {
  84.   AH = 0x52;                            //
  85.   $ INT 0x21;                           // Get the DOS data segment
  86.   BX -= 2;                              //    in ES
  87.   ES = ESWORD[BX];                      //
  88.   do{
  89.     $ CLD;                              //
  90.     SI = name;                          //
  91.     DI = 8;                             // Compare the name to 'name'
  92.     CX = len;                           //
  93.     $ REPZ                              //
  94.     $ CMPSB                             //
  95.     IF( ZEROFLAG ){
  96.       DX = ES+1;
  97.       AX = CS;                          // First make sure
  98.       IF( AX != DX )                    //   it is not ourself
  99.         IF( DX == ESWORD[1] )           // Does the block owns itself?
  100.           return(DX);                   // Returns true  
  101.     }
  102.     ES = ES+ESWORD[3]+1;                // Go to the next MCB
  103.   }while(ESBYTE[0] != 0x5A);            // Loop until the last MCB
  104.   return(0);                            // Return false
  105. }
  106.  
  107. ? define ENV_OFS   0x002C    // offset in the PSP that holds the env. segment
  108.  
  109. : void RELEASEENV()
  110. {
  111.   ES = DSWORD[ENV_OFS];
  112.   AH = 0x49;
  113.   $ INT 0x21;
  114. }
  115.  
  116. // More FixPath-specific functions
  117.  
  118. void installint ()      // install our interrupt routine
  119. word seg;
  120. {
  121.   @RELEASEENV();
  122.   seg = @GETMEM(#endofdoshandle - #olddoshandle - 1 / 16 + 1);
  123.   IF( seg == 0 )
  124.     @DOSWRITESTR("ERROR:  environment size too small to install FixPath\n$");
  125.   ELSE{
  126.     ES = seg-1;                        // change the MCB of the block
  127.     ESWORD[1]=seg;                     //   to tell DOS that it owns itself
  128.     COPYFAR(ES,0x08,DS,#progname,len_progname); // write the name in the MCB
  129.     GETINTVECT(#olddoshandle,0x21);    // get old DOS interrupt handle 
  130.     COPYFAR(seg,OLD21_OFS,CS,#olddoshandle,#endofdoshandle-#olddoshandle); 
  131.                    // copy the interrupt routine into the new segment
  132.     SETINTVECT( ,0x21,seg,NEW21_OFS);  // attach to DOS interrupt 
  133.   }
  134. }
  135.  
  136. void uninstall(word seg)  // remove FixPath from memory if possible
  137. word currentint21[2];
  138. {
  139.   GETINTVECT(#currentint21,0x21);  // Get the current DOS interrupt address
  140.   IF( DSWORD[#currentint21] == NEW21_OFS ) // Is it the resident
  141.     IF( DSWORD[#currentint21+2] == seg ){  //     FixPath?
  142.       ES=seg;
  143.       SETINTVECT( ,0x21,ESWORD[OLD21_OFS+2],ESWORD[OLD21_OFS]); 
  144.       @FREEMEM(seg);
  145.       @DOSWRITESTR("FixPath successfully removed from memory.\n$");
  146.       return();
  147.     }
  148.   @DOSWRITESTR("ERROR:  Unable to remove FixPath from memory.\n$");
  149. }  
  150.  
  151. main()
  152. byte str[80];
  153. {
  154.   @DOSWRITESTR("FixPath 1.2 by Jean-Marc Lasgouttes.\n$");
  155.   instcheck(#progname, len_progname);
  156.   DX = AX;             // AX = instcheck(): 0 or the segment where FixPath is
  157.   AX = @PARAMCOUNT();
  158.   IF(AX==0)
  159.     IF( DX != 0 )
  160.       @DOSWRITESTR("ERROR:  FixPath is already installed.\n$");
  161.     ELSE
  162.       installint();
  163.   ELSE{
  164.     strcpy(#str, @PARAMSTR(0));
  165.     @STR_UP(#str);
  166.     IF( @STRCMP(#str,"/U") )
  167.       @DOSWRITESTR(#usage);
  168.     ELSE
  169.       IF( DX != 0 )
  170.         uninstall(DX);
  171.       ELSE
  172.         @DOSWRITESTR("ERROR:  FixPath is not installed.\n$"); 
  173. }
  174.       
  175. } /* Terminate but don't stay resident.  The interrupt routine is in the
  176.      environment segment. */
  177.  
  178. /* end of FIXPATH.C-- */
  179.